/**
 * 修复材质引用脚本
 * 扫描所有项目的所有场景，收集材质使用情况，并更新到材质JSON文件的usedByNodes字段
 */

const fs = require('fs').promises;
const fsSync = require('fs');
const path = require('path');
const { PROJECTS_DIR } = require('../utils/constants');
const { readProjectsIndex } = require('../services/projectService');
const { readMaterialConfig, writeMaterialConfig, getAllMaterials } = require('../utils/materialConfigHelper');

/**
 * 读取场景的nodes.json文件
 */
async function readSceneNodes(projectPath, sceneId) {
    try {
        const nodesPath = path.join(projectPath, 'scenes', sceneId, 'nodes.json');
        const content = await fs.readFile(nodesPath, 'utf-8');
        return JSON.parse(content);
    } catch (error) {
        console.warn(`   ⚠️ 读取场景节点失败 (${sceneId}):`, error.message);
        return null;
    }
}

/**
 * 从节点中提取材质引用（mesh级别）
 */
function extractMaterialReferences(nodesData, sceneId) {
    const references = new Map(); // Map<materialId, Array<{nodeId, meshId, meshName}>>
    
    if (!nodesData || !nodesData.nodes) {
        return references;
    }
    
    // 遍历所有节点
    for (const node of nodesData.nodes) {
        // 跳过根节点
        if (node.type === 'root' || node.id === 'root') {
            continue;
        }
        
        // 查找model组件
        const modelComponent = node.components?.find(c => c.type === 'model');
        if (!modelComponent || !modelComponent.meshMaterials) {
            continue;
        }
        
        // 遍历mesh材质绑定
        for (const [meshId, binding] of Object.entries(modelComponent.meshMaterials)) {
            const materialId = binding.materialId;
            
            // 跳过无效的materialId
            if (!materialId || materialId === "0") {
                continue;
            }
            
            // 记录引用（精确到mesh级别）
            if (!references.has(materialId)) {
                references.set(materialId, []);
            }
            references.get(materialId).push({
                nodeId: node.id,
                meshId: meshId,
                meshName: binding.meshName || meshId
            });
        }
    }
    
    return references;
}

/**
 * 获取项目的所有场景ID
 */
async function getProjectScenes(projectPath) {
    try {
        const scenesDir = path.join(projectPath, 'scenes');
        if (!fsSync.existsSync(scenesDir)) {
            return [];
        }
        
        const entries = await fs.readdir(scenesDir, { withFileTypes: true });
        return entries
            .filter(entry => entry.isDirectory())
            .map(entry => entry.name);
    } catch (error) {
        console.warn('   ⚠️ 读取场景目录失败:', error.message);
        return [];
    }
}

/**
 * 修复单个项目的材质引用
 */
async function fixProjectMaterialReferences(projectMeta) {
    const projectId = projectMeta.id;
    const projectPath = path.join(PROJECTS_DIR, projectMeta.path);
    
    console.log(`\n📦 处理项目: ${projectMeta.name} (${projectId})`);
    
    // 1. 获取项目的所有材质
    const materialsDir = path.join(projectPath, 'materials');
    if (!fsSync.existsSync(materialsDir)) {
        console.log('   ℹ️ 项目没有材质目录，跳过');
        return { updated: 0, total: 0 };
    }
    
    const materials = await getAllMaterials(materialsDir);
    console.log(`   📄 找到 ${materials.length} 个材质`);
    
    if (materials.length === 0) {
        return { updated: 0, total: 0 };
    }
    
    // 2. 获取项目的所有场景
    const sceneIds = await getProjectScenes(projectPath);
    console.log(`   🎬 找到 ${sceneIds.length} 个场景`);
    
    if (sceneIds.length === 0) {
        return { updated: 0, total: materials.length };
    }
    
    // 3. 收集所有场景中的材质引用（mesh级别）
    // Map<materialId, Array<{sceneId, nodeId, meshId, meshName}>>
    const allReferences = new Map();
    
    for (const sceneId of sceneIds) {
        console.log(`   🔍 扫描场景: ${sceneId}`);
        
        const nodesData = await readSceneNodes(projectPath, sceneId);
        if (!nodesData) {
            continue;
        }
        
        const sceneReferences = extractMaterialReferences(nodesData, sceneId);
        
        // 合并到总引用表
        for (const [materialId, meshRefs] of sceneReferences.entries()) {
            if (!allReferences.has(materialId)) {
                allReferences.set(materialId, []);
            }
            
            // 添加scene信息到每个mesh引用
            for (const meshRef of meshRefs) {
                allReferences.get(materialId).push({
                    sceneId,
                    nodeId: meshRef.nodeId,
                    meshId: meshRef.meshId,
                    meshName: meshRef.meshName
                });
            }
            
            console.log(`      ✓ 材质 ${materialId}: ${meshRefs.length} 个mesh`);
        }
    }
    
    // 4. 更新材质配置文件
    let updatedCount = 0;
    const timestamp = new Date().toISOString();
    
    for (const material of materials) {
        const materialId = material.id;
        const references = allReferences.get(materialId);
        
        // 构建usedByMeshes数组（mesh级别）
        const usedByMeshes = [];
        if (references) {
            for (const ref of references) {
                usedByMeshes.push({
                    sceneId: ref.sceneId,
                    nodeId: ref.nodeId,
                    meshId: ref.meshId,
                    meshName: ref.meshName,
                    addedAt: timestamp
                });
            }
        }
        
        // 对比现有的引用数据
        const existingUsedByMeshes = material.usedByMeshes || [];
        const hasChanges = JSON.stringify(usedByMeshes.map(r => ({ 
            sceneId: r.sceneId, 
            nodeId: r.nodeId, 
            meshId: r.meshId 
        }))) !== JSON.stringify(existingUsedByMeshes.map(r => ({ 
            sceneId: r.sceneId, 
            nodeId: r.nodeId, 
            meshId: r.meshId 
        })));
        
        if (hasChanges) {
            material.usedByMeshes = usedByMeshes;
            material.updatedAt = timestamp;
            
            await writeMaterialConfig(materialsDir, materialId, material);
            updatedCount++;
            
            console.log(`   ✅ 更新材质引用: ${material.displayName || material.name} (${usedByMeshes.length} 个mesh引用)`);
        } else if (usedByMeshes.length > 0) {
            console.log(`   ℹ️ 材质引用无变化: ${material.displayName || material.name} (${usedByMeshes.length} 个mesh引用)`);
        }
    }
    
    return { updated: updatedCount, total: materials.length };
}

/**
 * 主函数
 */
async function main() {
    try {
        console.log('🚀 开始修复材质引用...\n');
        
        // 1. 读取项目索引
        const index = await readProjectsIndex();
        const projects = index.projects || [];
        
        console.log(`📋 找到 ${projects.length} 个项目\n`);
        
        if (projects.length === 0) {
            console.log('⚠️ 没有找到任何项目');
            return;
        }
        
        // 2. 遍历所有项目
        let totalUpdated = 0;
        let totalMaterials = 0;
        
        for (const projectMeta of projects) {
            try {
                const result = await fixProjectMaterialReferences(projectMeta);
                totalUpdated += result.updated;
                totalMaterials += result.total;
            } catch (error) {
                console.error(`❌ 处理项目失败 (${projectMeta.id}):`, error);
            }
        }
        
        // 3. 输出总结
        console.log('\n' + '='.repeat(60));
        console.log('📊 修复完成统计:');
        console.log(`   - 总材质数: ${totalMaterials}`);
        console.log(`   - 已更新: ${totalUpdated}`);
        console.log(`   - 无变化: ${totalMaterials - totalUpdated}`);
        console.log('='.repeat(60));
        
    } catch (error) {
        console.error('❌ 脚本执行失败:', error);
        process.exit(1);
    }
}

// 执行脚本
if (require.main === module) {
    main().then(() => {
        console.log('\n✅ 脚本执行完成');
        process.exit(0);
    }).catch(error => {
        console.error('\n❌ 脚本执行失败:', error);
        process.exit(1);
    });
}

module.exports = { fixProjectMaterialReferences };

